
import { ZRenderComp } from '../../../common/component/zrComp';

import { TextureLoader } from '../../../common/image/textureLoader';
import { IndexImage } from '../../../common/image/index';

class WeaponBundle {
  // 原来就有的数据
  sheetUrl = '';
  category = '';
  /** @type {IconDef[]} */
  weapons = [];
  /** @type {IconDef[]} */
  props = [];

  // 图像
  loaded = false;
  /** @type {Promise<this>} */
  loadTask = null;

  loadImage() {
    if (this.loaded) {
      return Promise.resolve(this);
    }

    const loader = new TextureLoader();
    return this.loadTask = loader.load(this.sheetUrl)
      .then(() => {
        const sheet = loader.findSheet(this.sheetUrl);
        const textureMap = sheet.allFromCache();

        let iconMap = {};
        this.weapons.forEach(w => iconMap[w.name] = w);
        this.props.forEach(w => iconMap[w.name] = w);
        for (let name in textureMap) {
          /** @type {IconDef} */
          let icon = iconMap[name];
          if (!icon) continue;
          icon.setImage(textureMap[name]);
        }
        this.loaded = true;
        return this;
      });
  }
}

class IconDef {
  /**
   * @param {{name:string,color:string}} args
   */
  constructor(args) {
    this.name = args.name;
    this.color = args.color;
  }

  /**
   * @param {IndexImage} image 
   */
  setImage(image) {
    this.width = image.width;
    this.height = image.height;

    // layer1 : 底, 一般每个 item 都几乎一样的
    // layer2 : content
    // layer3 : 边框 + 最亮的
    const painter = image.createPainter();
    this.path1 = painter.toPath((c) => c.a > 0).path;
    this.path2 = painter.toPath((c) => c.a > 0 && c.r > 124).path;
    this.path3 = painter.toPath((c) => c.a > 0 && c.r < 124).path;
  }

  getColors() {
    let list = cacheColor.filter(c => c.type == this.color);
    return list.length ? list[0].values : defaultColors;
  }
}

/** @type {WeaponBundle[]} */
let cacheBundles;
/** @type {{type:string,values:string[]}[]} */
let cacheColor;
const defaultColors = ["#4b97ca","#1d4f81","#0e365e"];

function load(context) {
  if (cacheBundles) {
    return Promise.resolve(cacheBundles);
  }

  const url = context.assetPath('assets/loadout/loadout_weapon_details.json');
  return fetch(url)
    .then(d => d.json())
    .then(d => {
      cacheColor = d.colors;
      /** @type {Object[]} */
      let list = d.bundles;
      let bundles = list.map(dd => {
        let bundle = new WeaponBundle();
        bundle.sheetUrl = url.substring(0, url.lastIndexOf('/')) + '/' + dd.sheet;
        bundle.category = dd.category;
        bundle.weapons = dd.weapons.map(w => new IconDef(w));
        bundle.props = dd.props.map(w => new IconDef(w));
        return bundle;
      });
      return cacheBundles = bundles;
    })
    .then(bundles => Promise.all(bundles.map(b => b.loadImage())));
}

class WeaponIcon extends ZRenderComp {
  /**
   * @param args
   *   传入的 x, y 是作为 icon 左上角位置
   */
  constructor(args) {
    super(args.parent);
    this.useParentZRenderInstance(args.x, args.y);
    /** @type {string} */ this.type = args.type;
    /** @type {number} width = height, 期望大小 */ this.width = args.width;

    /** @type {IconDef} */ this.iconDef = args.iconDef;
    this.scale = args.scale;
    this.zIndex = args.zIndex;
    this.z = args.z;
  }

  init() {
    const { z, zIndex, iconDef, scale } = this;
    const { path1, path2, path3, width:pathWidth } = iconDef;
    /** @type {string[]} */ const colors = iconDef.getColors();

    const sp1 = this.createPathFromString(path1)
      .fill(colors[1])
      .shadow(colors[1], scale * 2)
      .position(0, 0)
      .scale(scale)
      .opacity(0)
      .z(zIndex, z)
      .build();
    const sp2 = this.createPathFromString(path2)
      .fill(colors[0])
      .position(0, 0)
      .scale(scale)
      .opacity(0)
      .z(zIndex, z + 1)
      .build();
    const sp3 = this.createPathFromString(path3)
      .fill(colors[2])
      .position(0, 0)
      .scale(scale)
      .opacity(0)
      .z(zIndex, z + 2)
      .build();
    this.createAnimation('opacity', 0)
      .whenUpdated(p => {
        sp1.opacity(p.value * 0.6);
        sp2.opacity(p.value);
        sp3.opacity(p.value);
      })
      .update()
      .when(0, 0)
      .when(500, 1)
      .commit();

    this.spW1 = this.createPathFromString(path1)
      .fill('white')
      .shadow('white', scale * 2)
      .position(0, 0)
      .opacity(0.05)
      .blend('lighter')
      .scale(scale)
      .z(zIndex, z)
      .build();
    this.spW3 = this.createPathFromString(path2)
      .fill('white')
      .position(0, 0)
      .scale(scale)
      .z(zIndex, z + 2)
      .build();
    this.spClip = this.createPathFromString('M0,0h9l40,40h-9Z M-5,0h3l40,40h-3Z')
      .defineAsClip()
      .position(-pathWidth * 2, 0)
      .build();
    this.spW1.setClipPath(this.spClip);
    this.spW3.setClipPath(this.spClip);
    this.lastFlashTime = Date.now();

    this.ticker(now => {
      if (now - this.lastFlashTime <= 6000) {
        return;
      }
      this.lastFlashTime = now;
      this.createAnimation('flash.x')
        .whenUpdated(p => this.spClip.moveTo(p.value))
        .update()
        .when(0, -iconDef.width * 2)
        .when(700, iconDef.width * 2)
        .commit();
    });
  }
}

export {
  WeaponBundle, IconDef, WeaponIcon,
  load,
};
